package main

import (
	"crypto/sha1"
	"fmt"
	"github.com/xtaci/kcp-go/v5"
	"go.uber.org/atomic"
	"golang.org/x/crypto/pbkdf2"
	"time"
	"wths/wthsjy-im/plugins/log"
	"wths/wthsjy-im/protocol"
)

const (
	kcpKeyPassword = "___自定义密码____"
	kcpKeySalt     = "___自定义盐_____"
)

func kcpBlockCrypt() (kcp.BlockCrypt, error) {
	key := pbkdf2.Key([]byte(kcpKeyPassword), []byte(kcpKeySalt), 1024, 32, sha1.New)
	return kcp.NewAESBlockCrypt(key)
}

func main() {
	block, _ := kcpBlockCrypt()
	sess, err := kcp.DialWithOptions("101.34.7.166:9000", block, 10, 3)
	if err != nil {
		panic(err)
	}

	// 认证
	data := getAuthPacketBytes()
	_, err = sess.Write(data)
	if err != nil {
		panic(err)
	}

	authAck, err := protocol.ReadIO(sess)
	if err != nil {
		panic(err)
	}
	log.Debug("kcp").Msg(authAck.Head(), authAck.Data())

	// 订阅
	data = getSubscribePacketBytes()
	_, err = sess.Write(data)
	if err != nil {
		panic(err)
	}

	subAck, err := protocol.ReadIO(sess)
	if err != nil {
		panic(err)
	}
	log.Debug("kcp").Msg(subAck.Head(), subAck.Data())

	go func() {
		for {
			sess.SetWriteDeadline(time.Now().Add(time.Second * 60))
			time.Sleep(time.Second * 10)
			_, err := sess.Write(getPingBytes())
			log.Error("kcp_ping").Msgf("%v", err)
		}
	}()
	for {
		sess.SetReadDeadline(time.Now().Add(time.Second * 60))
		pkg, err := protocol.ReadIO(sess)
		if err != nil {
			log.Error("kcp").Msgf("%v", err)
		}
		log.Debug("kcp").Msg(pkg.Head(), string(pkg.Data()))
	}

}

var st = time.Now().UnixNano()
var index atomic.Int64

func getAuthPacketBytes() []byte {
	p, _ := protocol.NewConnectPacket(fmt.Sprintf("client_%d_%d", st, index.Add(1)), false)
	bs, _ := protocol.Encode(p)
	log.Debug("getAuthPacketBytes").Msg(len(bs))
	return bs
}
func getSubscribePacketBytes() []byte {
	p, _ := protocol.NewSubscribePacket([]string{"topic111"})
	//p, _ := protocol.NewSubscribePacket([]string{fmt.Sprintf("topic_%d", time.Now().UnixNano())})
	bs, _ := protocol.Encode(p)
	log.Debug("getSubscribePacketBytes").Msg(len(bs))
	return bs
}

func getPingBytes() []byte {
	p := protocol.NewPingPacket()
	bs, _ := protocol.Encode(p)
	log.Debug("getPingBytes").Msg(len(bs))
	return bs
}
